#!/usr/bin/ruby
#
# Simplebeat Copyright (C) 2007 Leroy van Logchem
#                               <leroy.vanlogchem@gmail.com>
#
# This file is part of Simplebeat
#
# Simplebeat is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3 of the License, or
# any later version.
#
# Simplebeat is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
#
#

# Lets add our library directory to Ruby's search path
$: << File.expand_path(File.dirname(__FILE__) + "/lib")

require 'socket'
require 'init.rb'

puts "Started daemonized Simplebeat.slave"

# Run as daemon
# parent process exits to pass child to init(1).
fork and exit

# child becomes session leader and disassociates controlling tty.
# namely do Process.setpgrp + \alpha.
Process.setsid

@report = nil

Syslog.info("-----------------------------------------------------")
Syslog.info("Simplebeat.slave starting")
Syslog.info("-----------------------------------------------------")

def setuplisten
  #
  # Setup UDP binding for receiving
  #
  $udp_in = UDPSocket.new
  $port = @udp_range.first.to_i
  begin
    $udp_in.bind('0.0.0.0', $port)
  rescue Errno::EADDRINUSE
    $port = $port.succ if($port < @udp_range.last)
    retry
  end
  Syslog.info("Listening on UDP port #{$port}")
end

def detectmaster ( udp_in )
  timeout = (@deadtime/3).to_i
  if IO.select([$udp_in], nil, nil, timeout)
    # Prepare the socket for the next round by flusing the data
    return true if $udp_in.recvfrom(1024)[0].match('Simplebeat')
    return false
  else
    return false
  end
end

begin
  loop do
    setuplisten unless $udp_in
    if detectmaster($udp_in)
      if @report.nil?
        Syslog.info("slave detected master, no action required")
        @report = false
      end
      next
    end
    if detectmaster($udp_in)
      late = (@deadtime/3)
      Syslog.info("Warning: >#{late} t[s] slow master detected, no action required")
      next
    end
    if detectmaster($udp_in)
      late = (@deadtime/3) * 2
        Syslog.info("Critical: >#{late} t[s] slow master detected, no action required")
    else
          # We didnt recieve anything from the master
	  break
    end
  end

  Syslog.info("Starting failover, master didnt send for #{@deadtime} seconds!")
  exec File.expand_path(File.dirname(__FILE__) + "/failover.rb")

  Syslog.info("-----------------------------------------------------")
  Syslog.info("SEVERE! Call to failover failed!")
  Syslog.info("-----------------------------------------------------")

end
